﻿namespace SuperModel.Generation
{
    using System;
    using System.Reflection;
    using System.Reflection.Emit;
    
    /// <summary>
    /// Emit Utilities
    /// </summary>
    internal class EmitUtil
    {
        /// <summary>
        /// Prevents a default instance of the EmitUtil class from being created.
        /// </summary>
        private EmitUtil()
        {
        }

        /// <summary>
        /// Adds an Attribute to a Dynamically generated Type
        /// </summary>
        /// <param name="newType">Dynamic type</param>
        /// <param name="attributeType">Attribute to add</param>
        public static void AddAttributeToType(TypeBuilder newType, Type attributeType)
        {
            if (!typeof(Attribute).IsAssignableFrom(attributeType))
            {
                throw new ArgumentException("The attributeType parameter must be an attribute");
            }

            // Add the Attribute via Spring
            newType.SetCustomAttribute(CreateCustomAttribute(attributeType));
        }

        /// <summary>
        /// Add an attribute to an event
        /// </summary>
        /// <param name="newEvent">Dynamic event</param>
        /// <param name="attributeType">Attribute to add</param>
        public static void AddAttributeToField(FieldBuilder newEvent, Type attributeType)
        {
            if (!typeof(Attribute).IsAssignableFrom(attributeType))
            {
                throw new ArgumentException("The attributeType parameter must be an attribute");
            }

            newEvent.SetCustomAttribute(CreateCustomAttribute(attributeType));
        }

        /// <summary>
        /// Creates a Custom Attribute
        /// </summary>
        /// <param name="attributeType">
        /// The attribute type.
        /// </param>
        /// <returns>
        /// A custom attribute builder
        /// </returns>
        private static CustomAttributeBuilder CreateCustomAttribute(Type attributeType)
        {
            ConstructorInfo ctor = attributeType.GetConstructor(Type.EmptyTypes);
            return new CustomAttributeBuilder(ctor, new object[] { });
        }
    }
}
